package ucd.csi.comp30220.fall2011.oteop.collision;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import ucd.csi.comp30220.fall2011.oteop.OTEOP;
import ucd.csi.comp30220.fall2011.oteop.util.EndPoint;
import ucd.csi.comp30220.fall2011.oteop.util.ServiceFinder;

/**
 * Collision Subscriber
 * 
 * @author David Haddock
 *
 */
public class CollisionSubscriber implements MessageListener {
	
	/**
	 * The subscribers to the collision information
	 */
	private List<CollisionListener> listeners = new ArrayList<CollisionListener>();
	
	/**
	 * Setup the listener to the JMS topic
	 * @throws NamingException
	 * @throws JMSException
	 */
	public CollisionSubscriber() throws Exception {
		long timeout = 10*1000;
	    EndPoint endPoint = ServiceFinder.findService(
	            OTEOP.JMDNS_TYPE_TCP_LOCAL, Collision.JMDNS_SUB_TYPE, "collision", timeout);
	    if (endPoint == null)
	        throw new Exception("Failed to get an implementation of Collision in " + timeout + "ms");
	    String providerUrl = "tcp://" +endPoint.getHost() +":" +endPoint.getPort();

		Hashtable<String, String> properties = new Hashtable<String, String>();
		properties.put(Context.INITIAL_CONTEXT_FACTORY, OTEOP.JAVA_NAMING_FACTORY_INITIAL);
		properties.put(Context.PROVIDER_URL, providerUrl);
		Context context = new InitialContext(properties);
		ConnectionFactory factory = (ConnectionFactory) context.lookup("ConnectionFactory");
		Connection connection = factory.createConnection();
		
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		final Destination destination = (Destination) context.lookup("topic1");
		MessageConsumer consumer = session.createConsumer(destination);
		consumer.setMessageListener(this);
		connection.start();
		System.out.println("JMS subscription to: " +providerUrl);
    }
    
	/**
	 * Add a new listener.
	 * @param listener
	 */
    public void addListener(CollisionListener listener) {
        listeners.add(listener);
    }

    /**
     * The publisher has published new information.
     * Get the information from the topic
     * Call each of the subscribers listeners with the information
     */
	public void onMessage(Message arg0) {
		ObjectMessage message = (ObjectMessage) arg0;
		CollisionInfo status;
		try {
			status = (CollisionInfo) message.getObject();
			for (CollisionListener listener : listeners) {
	            listener.onCollisionUpdate(status);
			}
		} catch (JMSException e) {
			System.out.println("The information could not be received from the topic");
			e.printStackTrace();
		}
	}
}
